package com.ld.poetry.utils.storage;

import com.google.gson.Gson;
import com.ld.poetry.entity.Resource;
import com.ld.poetry.service.ResourceService;
import com.ld.poetry.constants.CommonConst;
import com.ld.poetry.vo.FileVO;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.BatchStatus;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Component
@ConditionalOnProperty(name = "qiniu.enable", havingValue = "true")
public class QiniuUtil implements StoreService {

    /**
     * 七牛云
     */
    @Value("${qiniu.accessKey}")
    private String accessKey;

    @Value("${qiniu.secretKey}")
    private String secretKey;

    @Value("${qiniu.bucket}")
    private String bucket;

    @Value("${qiniu.downloadUrl}")
    private String downloadUrl;

    @Value("${qiniu.resourceUrl}")
    private String resourceUrl;

    private static final long EXPIRE_SECONDS = 60L;
    private static final long F_SIZE_LIMIT = 20971520L;

    @Autowired
    private ResourceService resourceService;

    public String getToken(String key) {
//        StringMap putPolicy = new StringMap();
//        putPolicy.put("fsizeLimit", F_SIZE_LIMIT);
        Auth auth = Auth.create(accessKey, secretKey);
//        return auth.uploadToken(bucket, key, EXPIRE_SECONDS, putPolicy);
        return auth.uploadToken(bucket, key, 3600, new StringMap().put("insertOnly", 0));
    }

    @Override
    public void deleteFile(List<String> files) {
        if (CollectionUtils.isEmpty(files)) {
            return;
        }
        //构造一个带指定 Region 对象的配置类
        Configuration cfg = new Configuration(Region.region0());
        Auth auth = Auth.create(accessKey, secretKey);
        BucketManager bucketManager = new BucketManager(auth, cfg);
        try {
            //单次批量请求的文件数量不得超过1000
            String[] keyList = files.stream().map(path -> path.replace(downloadUrl, "")).toArray(String[]::new);
            BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations();
            batchOperations.addDeleteOp(bucket, keyList);
            Response response = bucketManager.batch(batchOperations);
            BatchStatus[] batchStatusList = response.jsonToObject(BatchStatus[].class);
            for (int i = 0; i < keyList.length; i++) {
                BatchStatus status = batchStatusList[i];
                String key = keyList[i];
                if (status.code == 200) {
                    log.info("文件删除成功：" + key);
                    resourceService.lambdaUpdate().eq(Resource::getPath, downloadUrl + key).remove();
                } else {
                    log.error("文件删除失败：" + key + "，原因：" + status.data.error);
                }
            }
        } catch (QiniuException ex) {
            log.error("文件删除失败：" + ex.response.toString());
        }
    }

    @Override
    public FileVO saveFile(FileVO fileVO) {

        return uploadOSS(fileVO);
    }

    @Override
    public String getStoreName() {

        return StoreEnum.QINIU.getCode();
    }


    //密钥配置
//    Auth auth = Auth.create(accessKey, secretKey);
    //构造一个带指定 Region 对象的配置类
    //构造一个带指定 Region 对象的配置类
    //...其他参数参考类注释
    Configuration cfg = new Configuration(Zone.zone2());
    UploadManager uploadManager = new UploadManager(cfg);
    /**
     * 简单上传，使用默认策略，只需要设置上传的空间名就可以了
     *
     * @param fileName 文件上传至七牛云空间的名称
     * @return
     */
//    public String getUpToken(String fileName) {
//        //return auth.uploadToken(bucketname);
//        //<bucket>:<key>，表示只允许用户上传指定key的文件。在这种格式下文件默认允许“修改”，已存在同名资源则会被本次覆盖。
//        //如果希望只能上传指定key的文件，并且不允许修改，那么可以将下面的 insertOnly 属性值设为 1。
//        //第三个参数是token的过期时间
//        return auth.uploadToken(bucket, fileName, 3600, new StringMap().put("insertOnly", 0));
//    }


    /**
     * 普通上传
     *
//     * @param filePath 文件路径
//     * @param fileName 文件上传至七牛云空间的名称
     * @throws IOException
     */
    public FileVO uploadOSS(FileVO fileVO) {
        //构造一个带指定 Region 对象的配置类
        //构造一个带指定 Region 对象的配置类
        //...其他参数参考类注释
        Configuration cfg = new Configuration(Zone.zone2());
        UploadManager uploadManager = new UploadManager(cfg);
        String path = fileVO.getRelativePath();
        String absolutePath = downloadUrl + path;
        System.out.println("path======>" + path);
        System.out.println("absolutePath========>" + absolutePath);
        File localFile = new File("E:\\static\\" + fileVO.getFile().getOriginalFilename());
        try {
            fileVO.getFile().transferTo(localFile);
            String filePath = localFile.getAbsolutePath();
            System.out.println("filePath=========>" + filePath);
//            InputStream inputStream = fileVO.getFile().getInputStream();
//            System.out.println(inputStream);
//            调用put方法上传
            Response res = uploadManager.put(filePath, fileVO.getRelativePath(), getToken(fileVO.getRelativePath()));
//            Response res = uploadManager.put(filePath, fileVO.getRelativePath(), getToken(fileVO.getRelativePath()),null,null);
            //打印返回的信息
            System.out.println(res.bodyString());
            FileVO result = new FileVO();
            result.setAbsolutePath(absolutePath);
            result.setVisitPath(downloadUrl + path);
            log.info("absolutePath========>", resourceUrl + fileVO.getRelativePath());
            return result;
        } catch (QiniuException e) {
            Response r = e.response;
            // 请求失败时打印的异常的信息
            System.out.println(r.toString());
            try {
                //响应的文本信息
                System.out.println(r.bodyString());
            } catch (QiniuException e1) {
                //ignore
                e.printStackTrace();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return null;
    }

//    private FileVO uploadOSS(FileVO fileVO) {
//        log.info("fileVO=========>", fileVO);
//        //构造一个带指定 Region 对象的配置类
//        Configuration cfg = new Configuration(Region.autoRegion());
//        //cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
//        //...其他参数参考类注释
//        UploadManager uploadManager = new UploadManager(cfg);
////...生成上传凭证，然后准备上传
////        String accessKey = "";
////        String secretKey = "";
////        String bucket = "my-sg-blog1";
////默认不指定key的情况下，以文件内容的hash值作为文件名
//
//
//        String[] split = fileVO.getRelativePath().split("/");
//        String key = split[1];
//        System.out.println(key);
//        try {
//            //   byte[] uploadBytes = "hello qiniu cloud".getBytes("utf-8");
//            // ByteArrayInputStream byteInputStream=new ByteArrayInputStream(uploadBytes);
//            InputStream is = fileVO.getFile().getInputStream();
//
//            Auth auth = Auth.create(accessKey, secretKey);
//            String upToken = auth.uploadToken(bucket);
//
//            try {
//                Response response = uploadManager.put(is, key, upToken, null, null);
//                //解析上传成功的结果
//                DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
//                System.out.println(putRet.key);
//                System.out.println(putRet.hash);
//                FileVO result = new FileVO();
//                result.setAbsolutePath(resourceUrl + key);
//                result.setVisitPath(resourceUrl + key);
//                log.info("absolutePath========>", resourceUrl + key);
//                return result;
//            } catch (QiniuException ex) {
//                Response r = ex.response;
//                ex.printStackTrace();
//                try {
//                    System.err.println(r.bodyString());
//                } catch (QiniuException ex2) {
//                    //ignore
//                }
//            }
//        } catch (Exception ex) {
//            //ignore
//        }
//        return null;
//    }

    public Map<String, Map<String, String>> getFileInfo(List<String> files) {
        Map<String, Map<String, String>> result = new HashMap<>();

        //构造一个带指定 Region 对象的配置类
        Configuration cfg = new Configuration(Region.region0());
        Auth auth = Auth.create(accessKey, secretKey);
        BucketManager bucketManager = new BucketManager(auth, cfg);
        try {
            //单次批量请求的文件数量不得超过1000
            String[] keyList = files.toArray(new String[0]);
            BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations();
            batchOperations.addStatOps(bucket, keyList);
            Response response = bucketManager.batch(batchOperations);
            BatchStatus[] batchStatusList = response.jsonToObject(BatchStatus[].class);
            for (int i = 0; i < keyList.length; i++) {
                BatchStatus status = batchStatusList[i];
                String key = keyList[i];
                if (status.code == 200) {
                    //文件存在
                    Map<String, String> info = new HashMap<>();
                    info.put("size", String.valueOf(status.data.fsize));
                    info.put("mimeType", status.data.mimeType);
                    result.put(key, info);
                } else {
                    log.error(key + "：" + status.data.error);
                }
            }
        } catch (QiniuException ex) {
            log.error(ex.response.toString());
        }

        return result;
    }

    public void saveFileInfo() {
        List<Resource> resourceList = resourceService.lambdaQuery().select(Resource::getPath).list();
        List<String> paths = resourceList.stream().map(Resource::getPath).collect(Collectors.toList());

        //构造一个带指定 Region 对象的配置类
        Configuration cfg = new Configuration(Region.region0());
        Auth auth = Auth.create(accessKey, secretKey);
        BucketManager bucketManager = new BucketManager(auth, cfg);
        //文件名前缀
        String prefix = "";
        //每次迭代的长度限制，最大1000，推荐值 1000
        int limit = 1000;
        //指定目录分隔符，列出所有公共前缀（模拟列出目录效果）。缺省值为空字符串
        String delimiter = "";
        //列举空间文件列表
        BucketManager.FileListIterator fileListIterator = bucketManager.createFileListIterator(bucket, prefix, limit, delimiter);

        List<Resource> resources = new ArrayList<>();

        while (fileListIterator.hasNext()) {
            FileInfo[] items = fileListIterator.next();
            for (FileInfo item : items) {
                if (item.fsize != 0L && !paths.contains(downloadUrl + item.key)) {
                    Resource re = new Resource();
                    re.setPath(downloadUrl + item.key);
                    re.setType(CommonConst.PATH_TYPE_ASSETS);
                    re.setSize(Integer.valueOf(Long.toString(item.fsize)));
                    re.setMimeType(item.mimeType);
                    re.setStoreType(StoreEnum.QINIU.getCode());
                    re.setUserId(CommonConst.ADMIN_USER_ID);
                    resources.add(re);
                }
            }
        }

        if (!CollectionUtils.isEmpty(resources)) {
            resourceService.saveBatch(resources);
            System.out.println("保存数量：" + resources.size());
        }
        System.out.println("同步完成");
    }
}
